#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
文件接收服务端 - 支持在Android Termux或macOS本地测试运行
监听指定端口，接收从客户端发送的文件
"""

import socket
import os
import threading
from datetime import datetime

class FileReceiveServer:
    def __init__(self, host='0.0.0.0', port=8888, save_dir='./received_files'):
        self.host = host
        self.port = port
        self.save_dir = save_dir
        self.running = False
        
        # 确保保存目录存在
        if not os.path.exists(self.save_dir):
            os.makedirs(self.save_dir)
            print(f"创建目录: {self.save_dir}")
    
    def handle_client(self, client_socket, addr):
        """处理客户端连接"""
        try:
            print(f"[{datetime.now().strftime('%H:%M:%S')}] 客户端连接: {addr}")
            
            # 记录连接统计
            connection_count = getattr(self, '_connection_count', 0) + 1
            setattr(self, '_connection_count', connection_count)
            print(f"📊 这是第 {connection_count} 个连接")
            
            # 接收文件名长度
            filename_length_data = client_socket.recv(4)
            if len(filename_length_data) < 4:
                print("接收文件名长度失败")
                return
            
            filename_length = int.from_bytes(filename_length_data, 'big')
            
            # 接收文件名
            filename = client_socket.recv(filename_length).decode('utf-8')
            print(f"准备接收文件: {filename}")
            
            # 接收文件大小
            file_size_data = client_socket.recv(8)
            if len(file_size_data) < 8:
                print("接收文件大小失败")
                return
            
            file_size = int.from_bytes(file_size_data, 'big')
            print(f"文件大小: {file_size / (1024*1024):.2f} MB")
            
            # 生成保存路径 - 直接使用客户端发送的文件名，不添加时间戳
            save_path = os.path.join(self.save_dir, filename)
            
            # 接收文件数据
            received_size = 0
            buffer_size = 8192
            
            print(f"开始接收文件数据...")
            with open(save_path, 'wb') as f:
                while received_size < file_size:
                    remaining = file_size - received_size
                    chunk_size = min(buffer_size, remaining)
                    
                    chunk = client_socket.recv(chunk_size)
                    if not chunk:
                        print(f"\n⚠️ 连接意外断开，已接收: {received_size}/{file_size}")
                        break
                    
                    f.write(chunk)
                    received_size += len(chunk)
                    
                    # 显示进度
                    progress = (received_size / file_size) * 100
                    print(f"\r接收进度: {progress:.1f}% ({received_size}/{file_size})", end='')
                
                # 确保数据写入磁盘
                f.flush()
                os.fsync(f.fileno())
            
            if received_size == file_size:
                print(f"\n✅ 文件接收完整: {received_size} 字节")
                print(f"📁 文件保存成功: {save_path}")
                print(f"📈 连接统计: 已处理 {getattr(self, '_connection_count', 0)} 个连接")
                
                # 只有在文件接收完整时才发送确认
                # 发送确认消息
                print("📤 正在发送确认消息...")
                response = "文件接收成功".encode('utf-8')
                client_socket.send(len(response).to_bytes(4, 'big'))
                client_socket.send(response)
                
                # 确保数据发送完成
                try:
                    client_socket.shutdown(socket.SHUT_WR)  # 关闭发送，但保持接收
                    print("✅ 确认消息已发送")
                except:
                    print("⚠️ 关闭shutdown失败，但继续处理")
                
                print(f"✅ 文件传输完成，服务端将主动断开连接")
            else:
                print(f"\n❌ 文件接收不完整: {received_size}/{file_size} 字节")
                print("❌ 不发送确认消息，直接关闭连接")
                return
            
        except Exception as e:
            print(f"\n❌ 处理客户端时出错: {e}")
        finally:
            # 服务端主动关闭连接
            try:
                client_socket.close()
                print(f"[{datetime.now().strftime('%H:%M:%S')}] 服务端主动断开连接: {addr}\n")
            except:
                pass
    
    def start(self):
        """启动服务器"""
        server_socket = None
        try:
            server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server_socket.bind((self.host, self.port))
            server_socket.listen(5)
            
            self.running = True
            print(f"🚀 文件接收服务器启动成功!")
            print(f"🌍 监听地址: {self.host}:{self.port}")
            print(f"📁 保存目录: {os.path.abspath(self.save_dir)}")
            print(f"💻 本地测试请使用: python client.py 127.0.0.1 <文件名>")
            print(f"🔌 等待客户端连接...\n")
            
            while self.running:
                try:
                    client_socket, addr = server_socket.accept()
                    # 为每个客户端创建新线程
                    client_thread = threading.Thread(
                        target=self.handle_client,
                        args=(client_socket, addr)
                    )
                    client_thread.daemon = True
                    client_thread.start()
                except socket.error:
                    break
                    
        except Exception as e:
            print(f"服务器启动失败: {e}")
        finally:
            if server_socket:
                try:
                    server_socket.close()
                except:
                    pass
            print("服务器已关闭")
    
    def stop(self):
        """停止服务器"""
        self.running = False

def main():
    import argparse
    
    parser = argparse.ArgumentParser(
        description='文件接收服务端',
        epilog="本地测试: python server.py && python client.py 127.0.0.1 test.mp4"
    )
    parser.add_argument('--host', default='0.0.0.0', help='监听地址 (默认: 0.0.0.0)')
    parser.add_argument('--port', type=int, default=8888, help='监听端口 (默认: 8888)')
    parser.add_argument('--save-dir', default='./received_files', help='文件保存目录 (默认: ./received_files)')
    
    args = parser.parse_args()
    
    server = FileReceiveServer(args.host, args.port, args.save_dir)
    
    try:
        server.start()
    except KeyboardInterrupt:
        print("\n\n正在关闭服务器...")
        server.stop()

if __name__ == '__main__':
    main()